using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Resources;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections;
using WorldEditor.Properties;

using Core.Mapping;
using Core.Graphics;
using Core.Graphics.Layers;

namespace WorldEditor
{
    public partial class MapEditing : CanvasPanel
    {
        public MapEngine MapEngine { get { return mapEngine; } }
        public MapLayerTypes CurrentLayerType { get { return _CurrentLayerType; } set { _CurrentLayerType = value; } }
        public AutoTileLayer CurrentAutoTileLayer { get; set; }

        public override Rectangle DrawArea { 
            get { return _DrawArea; } 
            set {
                //use base method to set most values
                base.DrawArea = value;

                UpdateMaps();
            }
        }

        protected MapLayerTypes _CurrentLayerType;


        public TileWorld World { get { return _World; } }
        protected TileWorld _World;

        protected MapEngine mapEngine;

        public ArrayList Maps { get { return _Maps; } set { _Maps = value; } }
        private ArrayList _Maps;

        public MapEditing() : base()
        {
            InitializeComponent();

            _World = TileWorld.CurrentWorld;
            
            mapEngine = new MapEngine();
            mapEngine.Height = this.Height / Tile.ScaledTileHeight;
            mapEngine.Width = this.Width / Tile.ScaledTileWidth;

            UpdateDrawingArea();

            UpdateMaps();

            base.SizeChanged += new EventHandler(MapEditor_SizeChanged);
        }

        void MapEditor_SizeChanged(object sender, EventArgs e)
        {
            UpdateDrawingArea();
            UpdateMaps();
        }

        private void UpdateMaps()
        {
            _Maps = _World.GetMapsForRectangle(_DrawArea);
        }

        protected override void MouseMove(MouseEventArgs mouseargs)
        {
            base.MouseMove(mouseargs);

            _CurrentLocation = new Point(_CurrentTopLeftLocation.X + _CurrentDrawCursor.X, _CurrentTopLeftLocation.Y + _CurrentDrawCursor.Y);

            HoveringCoordinateChanged(_CurrentLocation);
        }

        protected override void MouseDown(object sender, MouseEventArgs e)
        {
            base.MouseDown(sender, e);

            _MouseStartWorldLocation = _CurrentLocation;
        }

        protected override void Pan()
        {
            _DrawArea = new Rectangle(_DrawArea.X - (_CurrentDrawCursor.X - _MouseStartScreenLocation.X),
                _DrawArea.Y - (_CurrentDrawCursor.Y - _MouseStartScreenLocation.Y),
                _DrawArea.Width, _DrawArea.Height);

            UpdateMaps();

            _MouseStartScreenLocation = _CurrentDrawCursor;

            _CurrentTopLeftLocation = new Point(_DrawArea.X, _DrawArea.Y);
        }

        protected override void Pencil()
        {
            switch (_CurrentLayerType)
            {
                case MapLayerTypes.Base:
                case MapLayerTypes.Terrain:
                case MapLayerTypes.TerrainDetail:
                case MapLayerTypes.TerrainSuperDetail:
                    _World.SetTileAtLocation(_CurrentLocation, _CurrentLayerType, new Tile(_PrimaryTile.SpriteID));
                    break;
                case MapLayerTypes.Collection:
                    CurrentAutoTileLayer.SetBaseTileAtWorldLocation(new Tile(_PrimaryTile.SpriteID), _CurrentLocation);
                    break;
            }
        }

        protected override void EyeDropper()
        {
            Tile t = _World.GetTileAtLocation(_CurrentLocation, _CurrentLayerType);

            if (t.SpriteID.ID >= 0)
            {
                TileSetTile tst = new TileSetTile(t.SpriteID.ID, TileSetCollection.GlobalTerrainTileSets[t.SpriteID.TileSetID]);

                _PrimaryTile = tst;
                //Execute the event
                OnPrimaryTileChanged();
            }
        }

        protected override void Eraser()
        {
            //If we have a selection
            if (_SelectedArea != null && _SelectedArea.Count > 0)
            {
                //for each tile in selection, erase it on that layer.
                foreach (Point pt in _SelectedArea)
                {
                    _World.SetTileAtLocation(pt, _CurrentLayerType, Tile.BlankTile);
                }
            }
            else
            {
                //If no selection just do a normal erase
                _World.SetTileAtLocation(_CurrentLocation, _CurrentLayerType, Tile.BlankTile);
            }
        }

        protected override void PaintBucket()
        {
            if (_SelectedArea != null && _SelectedArea.Count > 0)
            {
                foreach (Point pt in _SelectedArea)
                {
                    _World.SetTileAtLocation(pt, _CurrentLayerType, new Tile(_PrimaryTile.SpriteID));
                }
            }
            new FloodFill(_World, new Tile(_PrimaryTile.SpriteID), _CurrentLocation, _CurrentLayerType);
        }

        protected override void MagicWand()
        {
            _TempSelectedArea = ContiguousTiles.ContiguousTileFinder(_World, _CurrentLocation, _CurrentLayerType);
        }

        protected override void RectangleSelect()
        {
            ///TODO: Uncomment after we re-design the Contiguous area stuff
            int height = Math.Abs(_CurrentLocation.Y - _MouseStartWorldLocation.Y);
            int width = Math.Abs(_CurrentLocation.X - _MouseStartWorldLocation.X);

            _TempSelectedArea = new ArrayList(height * width);

            //For each x starting from our start point, going to our current mouse point
            for (int y = _MouseStartWorldLocation.Y; y < _CurrentLocation.Y; y++)
            {
                for (int x = _MouseStartWorldLocation.X; x < _CurrentLocation.X; x++)
                {
                    //Get Tiles and add to temp
                    _TempSelectedArea.Add(new Point(x, y));
                }
            }
        }

        protected override void EllipseSelect()
        {
            
        }

        protected override void Draw()
        {
            mapEngine.DrawMap(MapLayerBaseTypes.Base, spriteBatch, _DrawArea, _Maps);
            mapEngine.DrawMap(MapLayerBaseTypes.Terrain, spriteBatch, _DrawArea, _Maps);
            //Draw Extra Layers in this map
            mapEngine.DrawMap(MapLayerBaseTypes.Collection, spriteBatch, _DrawArea, _Maps);

            //Draw Cursor
            DrawCursor();

            //Draw Selection Area
            if (_SelectedArea != null)
                DrawSelection(_DrawArea, _SelectedArea);

            //Draw Selection Area
            if (_TempSelectedArea != null)
                DrawSelection(_DrawArea, _TempSelectedArea);


            base.Draw();
        }

        protected void DrawSelection(Rectangle drawArea, ArrayList list)
        {
            SpriteBatch.Begin(SpriteBlendMode.AlphaBlend);

            foreach(Point gp in list)
            {
                SpriteBatch.Draw(_CursorTile, new Rectangle((gp.X - _DrawArea.X) * Tile.ScaledTileWidth,
                    (gp.Y - _DrawArea.Y) * Tile.ScaledTileHeight, Tile.ScaledTileWidth, Tile.ScaledTileHeight), Color.Blue);
            }
            SpriteBatch.End();
        }

        protected void DrawCursor()
        {
            SpriteBatch.Begin(SpriteBlendMode.AlphaBlend);

            SpriteBatch.Draw(_CursorTile, new Rectangle(_CurrentDrawCursor.X * Tile.ScaledTileWidth,
                _CurrentDrawCursor.Y * Tile.ScaledTileHeight, Tile.ScaledTileWidth, Tile.ScaledTileHeight), Color.White);

            SpriteBatch.End();
        }
    }
}
